package com.yabushan.activiti.service;

import java.awt.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

import com.yabushan.activiti.domain.HistoryTaskInfo;
import com.yabushan.activiti.domain.NextStepAndUser;
import com.yabushan.activiti.domain.WorkflowConstants;
import com.yabushan.activiti.util.Constant;
import com.yabushan.activiti.util.Utils;
import com.yabushan.system.domain.ServiceStepConf;
import com.yabushan.system.domain.UumUserinfo;
import com.yabushan.system.service.IServiceStepConfService;
import com.yabushan.system.service.ISysUserService;
import com.yabushan.system.service.IUumUserinfoService;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.activiti.image.ProcessDiagramGenerator;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;


@Service
public class VacationServiceImpl implements  VacationService{

	@Autowired
	private HistoryQueryService historyQueryService;
	@Autowired
	private CommentService commentService;
	@Autowired
	private EngineService engineService;
	@Autowired
	private workflowUtilService workflowUtilService;
	@Autowired
	private VariablesService variablesService;
	@Autowired
	private ProcessDefinitionService processDefinitionService;
	@Autowired
	private IServiceStepConfService serviceStepConfService;
	@Autowired
	private  IUumUserinfoService uumUserinfoService;

	/**
	 * 实现类
	 */
	@Autowired
	private CustomProcessDiagramGeneratorService customProcessDiagramGeneratorService;

	@Override
	public List<HistoryTaskInfo> getAllHistoryStep(String processInstanceId, boolean isFinish, Integer firstResult, Integer maxResults) {
		List<HistoryTaskInfo> result =new ArrayList<HistoryTaskInfo>();
		//获取所有历史任务
		List<HistoricTaskInstance> list=historyQueryService.getHistoricTaskInstances(processInstanceId, isFinish, firstResult, maxResults);
		result = getHistoryInfo(list);
		return result;
	}

	public List<HistoryTaskInfo> getHistoryInfo(List<HistoricTaskInstance> list) {
		HistoryTaskInfo historyTaskInfo = null;
		List<HistoryTaskInfo> result = new ArrayList<HistoryTaskInfo>();
		if (list != null && list.size() > 0) {
			//遍历所有历史任务
			for (HistoricTaskInstance historicTaskInstance : list) {
				historyTaskInfo = new HistoryTaskInfo();
				historyTaskInfo.setHistoricTaskInstance(historicTaskInstance);
				//封装流程变量_未结束的流程
				Map<String, Object> taskObjectMap = historyQueryService.packageVariables(false,historicTaskInstance.getProcessInstanceId(), historicTaskInstance.getId());
				historyTaskInfo.setVarialbes(taskObjectMap);

				//封装批注信息
				List<Comment> comments = commentService.getCommentByTaskId(historicTaskInstance.getId());
				if (comments != null && comments.size() > 0) {
					historyTaskInfo.setTaskComment(comments);
				} else {
					historyTaskInfo.setTaskComment(null);
				}


				//封装表单变量
				Map<String, Object> stringObjectMap = historyQueryService.packageVariables(true,historicTaskInstance.getProcessInstanceId(), historicTaskInstance.getId());
				historyTaskInfo.setFormVarialbes(stringObjectMap);



				result.add(historyTaskInfo);
			}
		}
		return result;
	}
	/**
	 * 流程是否已经结束
	 *
	 * @param processInstanceId 流程实例ID
	 * @return
	 */
	public boolean isFinished(String processInstanceId) {
		return engineService.getHistoryService().createHistoricProcessInstanceQuery().finished()
				.processInstanceId(processInstanceId).count() > 0;
	}

	@Override
	public InputStream queryProImg(String businessKey) {
		//查询历史实例
		List<HistoricProcessInstance> list = engineService.getHistoryService()
				.createHistoricProcessInstanceQuery().processInstanceBusinessKey(businessKey)
				.list();
		if (list.size() == 0) {
			return null;
		}
		//processInstanceId
		String processInstanceId = list.get(0).getId();
		String processDefinitionId = list.get(0).getProcessDefinitionId();
		//获取历史流程实例
		//获取流程图
		BpmnModel bpmnModel = engineService.getRepositoryService().getBpmnModel(processDefinitionId);
		ProcessEngineConfiguration processEngineConfiguration = engineService.getProcessEngineConfiguration();
		Context.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration);

		ProcessDefinitionEntity definitionEntity = (ProcessDefinitionEntity) engineService.getRepositoryService().getProcessDefinition(processDefinitionId);

		List<HistoricActivityInstance> highLightedActivitList = engineService.getHistoryService().createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
		//高亮环节id集合
		List<String> highLightedActivitis = new ArrayList<>();
		//高亮线路id集合
		List<String> highLightedFlows = this.getHighLightedFlows(definitionEntity, highLightedActivitList);

		for (HistoricActivityInstance tempActivity : highLightedActivitList) {
			String activityId = tempActivity.getActivityId();
			highLightedActivitis.add(activityId);
		}

		// 第一种方式，单独返回流程图，不高亮显示
		//InputStream imageStream = diagramGenerator.generatePngDiagram(bpmnModel);

		//第二重方式，ProcessDiagramGenerator 对象显示,中文显示的是口口口，设置字体就好了
        /*
        ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
        InputStream inputStream = diagramGenerator.generateDiagram(
                bpmnModel,
                "png",
                highLightedActivitis,
                highLightedFlows,
                "宋体",
                "宋体",
                "宋体",
                processEngineConfiguration.getClassLoader(),
                1.0);*/

		// 第三种方式，需要重写ProcessDiagramGenerator的generateDiagram方法
		Set<String> currIds = engineService.getRuntimeService().createExecutionQuery().processInstanceId(processInstanceId).list()
				.stream().map(e -> e.getActivityId()).collect(Collectors.toSet());
		// 高亮图需要展示审批不通过高亮，需要将节点ID放入currIds集合中
		InputStream imageStream = customProcessDiagramGeneratorService.generateDiagram(bpmnModel, "png", highLightedActivitis,
				highLightedFlows, "宋体", "宋体", "宋体",
				null, 1.0,
				new Color[]{WorkflowConstants.COLOR_NORMAL, WorkflowConstants.COLOR_CURRENT}, currIds);
		return imageStream;
	}


	@Override
	public NextStepAndUser getFirstUser(String processKey, String userId, String empType, String processDefId, ProcessDefinitionEntity pd) {
		return null;
	}

	@Override
	public NextStepAndUser getFirstUser(String processKey, String userId, String empType ) {
		//根据流程key获取流程节点
		ServiceStepConf serviceStepConf=new ServiceStepConf();

		ProcessDefinition processDefinition = processDefinitionService.queryDefinitionsByDefinitionKey(processKey,true).get(0);
		serviceStepConf.setProcdefId(processDefinition.getKey());
		NextStepAndUser nextStepAndUser=new NextStepAndUser();
		List<ServiceStepConf> serviceStepConfs = serviceStepConfService.selectServiceStepConfList(serviceStepConf);
		//获取当前处理人所在组织
		UumUserinfo uumUserinfo = new UumUserinfo();
		uumUserinfo.setLoginId(userId);
		List<UumUserinfo> uumUserinfos1 = uumUserinfoService.selectUumUserinfoList(uumUserinfo);
		for (int i=0;i<serviceStepConfs.size();i++){
			ServiceStepConf step =serviceStepConfs.get(i);
			if(empType.equals(step.getStepName())){
				//判断该节点的审批类型
				if(("RY").equals(step.getDealType())){
					//具体到人
					nextStepAndUser.setNextUserId(step.getDealUserId());
					nextStepAndUser.setNextStep(step.getStepName());
					nextStepAndUser.setNextUserName(step.getDealUserName());

				}else if("SJ".equals(step.getDealType())){
					//直接上级
					nextStepAndUser.setNextUserId(step.getDealUserId());
					nextStepAndUser.setNextStep(step.getStepName());
					nextStepAndUser.setNextUserName(step.getDealUserName());


				}else if("LCJS_OFFICE".equals(step.getDealType())){//
					//根据流程角色到科室
					uumUserinfo=new UumUserinfo();
					if(uumUserinfos1.size()>0){
						uumUserinfo.setCompanyId(uumUserinfos1.get(0).getCompanyId());
						uumUserinfo.setDepartmentId(uumUserinfos1.get(0).getDepartmentId());
						uumUserinfo.setOfficeId(uumUserinfos1.get(0).getOfficeId());
					}
				}else if("LCJS_DEPT".equals(step.getDealType())){//
					//根据流程角色到部门
					uumUserinfo=new UumUserinfo();
					if(uumUserinfos1.size()>0){
						uumUserinfo.setCompanyId(uumUserinfos1.get(0).getCompanyId());
						uumUserinfo.setDepartmentId(uumUserinfos1.get(0).getDepartmentId());
					}
				}else if("LCJS_COMPANY".equals(step.getDealType())){
					//按流程角色
					uumUserinfo=new UumUserinfo();
					if(uumUserinfos1.size()>0){
						uumUserinfo.setCompanyId(uumUserinfos1.get(0).getCompanyId());
					}


				}

				if("LCJS_COMPANY".equals(step.getDealType()) ||
						"LCJS_DEPT".equals(step.getDealType())||
						"LCJS_OFFICE".equals(step.getDealType())){
					uumUserinfo.setEmployeeClass(step.getDealRoleId());
					List<UumUserinfo> uumUserinfos = uumUserinfoService.selectUumUserinfoList(uumUserinfo);
					StringBuffer accountBuf = new StringBuffer();
					StringBuffer deptInfoBuf = new StringBuffer();
					for (UumUserinfo user : uumUserinfos){
						accountBuf.append(user.getLoginId()).append(",");
						String dept=user.getDepartmentName()==null?"":"/"+user.getDepartmentName();
						deptInfoBuf.append(user.getRegionName()+"/"+user.getCompanyName()+dept).append(",");
					}
					nextStepAndUser.setNextUserId(accountBuf.toString().substring(0,accountBuf.length()-1));
					nextStepAndUser.setNextStep(step.getStepName());
					nextStepAndUser.setNextUserName(deptInfoBuf.toString().substring(0,deptInfoBuf.length()-1));

				}

				break;
			}
		}
		return nextStepAndUser;
	}


	@Override
	public String getRequestUserId(String taskId) {
		//获取流程发起人
		String requestUser =variablesService.getVariablesByTaskId(Constant.REQUEST_USER, taskId, false).toString();
		return requestUser;
	}


	/**
	 *
	 * @param list List<ActivityImpl>
	 * @param nodeId 用户节点ID
	 * @param isJumpStep 标识是否跳环节，1：是
	 * @return
	 */
	public NextStepAndUser getNextStepAndUserByNodeId(List<ActivityImpl> list,String nodeId,String isJumpStep){
		NextStepAndUser nextStepAndUser2 = new NextStepAndUser();
		for (ActivityImpl act1 : list) {
			if(nodeId.equals(act1.getId())){//公司总经理审批
				nextStepAndUser2.setNextStep(act1.getProperty("name").toString());
				nextStepAndUser2.setJumpStep(isJumpStep);//是否跳过步骤，1：是
				return nextStepAndUser2;
			}
		}
		return null;
	}


	/**
	 * 获取需要高亮的线
	 *
	 * @param processDefinitionEntity   节点
	 * @param historicActivityInstances 高亮点
	 */
	private List<String> getHighLightedFlows(
			ProcessDefinitionEntity processDefinitionEntity,
			List<HistoricActivityInstance> historicActivityInstances) {
		List<String> highFlows = new ArrayList<String>();// 用以保存高亮的线flowId
		for (int i = 0; i < historicActivityInstances.size() - 1; i++) {// 对历史流程节点进行遍历
			ActivityImpl activityImpl = processDefinitionEntity
					.findActivity(historicActivityInstances.get(i)
							.getActivityId());// 得到节点定义的详细信息
			List<ActivityImpl> sameStartTimeNodes = new ArrayList<ActivityImpl>();// 用以保存后需开始时间相同的节点
			ActivityImpl sameActivityImpl1 = processDefinitionEntity
					.findActivity(historicActivityInstances.get(i + 1)
							.getActivityId());
			// 将后面第一个节点放在时间相同节点的集合里
			sameStartTimeNodes.add(sameActivityImpl1);
			for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) {
				HistoricActivityInstance activityImpl1 = historicActivityInstances
						.get(j);// 后续第一个节点
				HistoricActivityInstance activityImpl2 = historicActivityInstances
						.get(j + 1);// 后续第二个节点
				if (activityImpl1.getStartTime().equals(
						activityImpl2.getStartTime())) {
					// 如果第一个节点和第二个节点开始时间相同保存
					ActivityImpl sameActivityImpl2 = processDefinitionEntity
							.findActivity(activityImpl2.getActivityId());
					sameStartTimeNodes.add(sameActivityImpl2);
				} else {
					// 有不相同跳出循环
					break;
				}
			}
			List<PvmTransition> pvmTransitions = activityImpl
					.getOutgoingTransitions();// 取出节点的所有出去的线
			for (PvmTransition pvmTransition : pvmTransitions) {
				// 对所有的线进行遍历
				ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition
						.getDestination();
				// 如果取出的线的目标节点存在时间相同的节点里，保存该线的id，进行高亮显示
				if (sameStartTimeNodes.contains(pvmActivityImpl)) {
					highFlows.add(pvmTransition.getId());
				}
			}
		}
		return highFlows;
	}


}
